// Win32 Application Support
// Copyright 2006 (C) Ralph Thomas


#include <toolkit/win32/application-win32.h>
#include <vector>
#include <algorithm>
#include <windows.h>
#include <objbase.h>

namespace toolkit {
	class applicationWin32Impl {
	  public:
		applicationWin32Impl() : looping( true ), hInstance( GetModuleHandle( NULL ) ) {}

		typedef std::vector<idle*> idleList;

		bool looping;
		idleList handlers;
		HINSTANCE hInstance;
	};

	applicationWin32::applicationWin32() : _impl( new applicationWin32Impl ) {}
	applicationWin32::~applicationWin32() {
		delete _impl;
	}

	applicationWin32& applicationWin32::getInstance() {
		static applicationWin32 aw;

		return aw;
	}
	application::initReturn applicationWin32::init() {
		if( _impl->hInstance == 0 ) return kNoServer;
		return kOk;
	}
	void applicationWin32::run() {
		MSG msg;

		//CoInitialize( 0 );
		if( _impl->hInstance == 0 ) return;
		//
		// Set up a timer so that we can make idle calls regularly.
		//
		SetTimer( 0, 0, 100, 0 );
		while( GetMessage( &msg, NULL, 0, 0 ) ) {
			if( msg.message == WM_TIMER && msg.hwnd == 0 ) {
				//
				// This one is for us. We need to call our idle handlers.
				//
				applicationWin32Impl::idleList ih( _impl->handlers );
				applicationWin32Impl::idleList::iterator first( ih.begin() );
				applicationWin32Impl::idleList::iterator last( ih.end() );

				while( first != last ) {
					idle* handler( *first );
					applicationWin32Impl::idleList::iterator end( _impl->handlers.end() );
					//
					// Verify that this handler is still in the idle handler list.
					//
					if( std::find( _impl->handlers.begin(), _impl->handlers.end(), handler ) != end && handler )
							handler->process();
					first++;
				}
			} else {
				TranslateMessage( &msg );
				DispatchMessage( &msg );
			}
		}
	}
	void applicationWin32::quit() {
		PostQuitMessage( 0 );
	}
	void applicationWin32::addIdle( idle* handler, unsigned int ) {
		removeIdle( handler );
		_impl->handlers.push_back( handler );
	}
	void applicationWin32::removeIdle( idle* h ) {
		applicationWin32Impl::idleList::iterator i;

		i = std::find( _impl->handlers.begin(), _impl->handlers.end(), h );
		if( i != _impl->handlers.end() ) _impl->handlers.erase( i );
	}
	//
	// Implementation of application::getInstance, which returns our
	// applicationWin32 singleton instance.
	//
	application& application::getInstance() {
		return applicationWin32::getInstance();
	}
};
